/**
 * @p.md
 * 
 * WasmCluster 模块，提供基于 WASM 的分布式集群功能
 */

import { PID } from '../actor/pid';
import { ActorSystem } from '../actor/actorSystem';
import { RootContext, RootContexts } from '../actor/rootContext';
import { Props } from '../actor/props';
import { WasmBridge, WasmBridgeFactory } from './wasmBridge';
import { WasmRemotingService, WasmRemotingFactory } from './wasmRemoting';

/**
 * 集群节点信息
 */
export interface ClusterNode {
  id: string;          // 节点 ID
  address: string;     // 节点地址
  roles: string[];     // 节点角色列表
  status: NodeStatus;  // 节点状态
  metadata?: Record<string, string>; // 节点元数据
}

/**
 * 节点状态枚举
 */
export enum NodeStatus {
  Up = 'up',           // 节点正常运行
  Down = 'down',       // 节点已关闭
  Leaving = 'leaving', // 节点正在离开集群
  Joining = 'joining'  // 节点正在加入集群
}

/**
 * 集群成员变化事件
 */
export interface MembershipEvent {
  eventType: MembershipEventType;
  node: ClusterNode;
}

/**
 * 成员事件类型枚举
 */
export enum MembershipEventType {
  Up = 'up',           // 节点上线
  Down = 'down',       // 节点下线
  Joined = 'joined',   // 节点加入
  Left = 'left'        // 节点离开
}

/**
 * 集群种子配置
 */
export interface ClusterSeed {
  host: string;
  port: number;
}

/**
 * 集群配置
 */
export interface ClusterConfig {
  clusterName: string;
  nodeName: string;
  address: string;
  roles: string[];
  seeds: ClusterSeed[];
  metadata?: Record<string, string>;
}

/**
 * 集群事件监听器
 */
export type ClusterEventListener = (event: MembershipEvent) => void;

/**
 * WASM 集群服务接口
 */
export interface WasmClusterService {
  /**
   * 初始化集群
   * @param config 集群配置
   */
  initialize(config: ClusterConfig): Promise<void>;

  /**
   * 获取集群节点列表
   * @returns 节点列表的 Promise
   */
  getNodes(): Promise<ClusterNode[]>;

  /**
   * 查找集群中的 Actor
   * @param clusterKind Actor 类型
   * @param identity 身份标识
   * @returns PID 的 Promise
   */
  getClusterActor(clusterKind: string, identity: string): Promise<PID>;

  /**
   * 向集群 Actor 发送消息
   * @param clusterKind Actor 类型
   * @param identity 身份标识
   * @param message 消息内容
   * @param sender 发送者 PID
   */
  sendClusterMessage(clusterKind: string, identity: string, message: any, sender?: PID): Promise<void>;

  /**
   * 向集群 Actor 发送请求并等待响应
   * @param clusterKind Actor 类型
   * @param identity 身份标识
   * @param message 消息内容
   * @param timeout 超时时间(毫秒)
   * @returns 响应的 Promise
   */
  requestClusterActor(clusterKind: string, identity: string, message: any, timeout?: number): Promise<any>;

  /**
   * 注册集群 Actor 类型
   * @param kind Actor 类型
   * @param props Actor 配置
   */
  registerClusterKind(kind: string, props: Props): void;

  /**
   * 添加集群事件监听器
   * @param listener 监听器函数
   * @returns 监听器 ID
   */
  addMembershipListener(listener: ClusterEventListener): number;

  /**
   * 移除集群事件监听器
   * @param listenerId 监听器 ID
   */
  removeMembershipListener(listenerId: number): void;

  /**
   * 优雅关闭集群
   */
  shutdown(): Promise<void>;
}

/**
 * WASM 集群服务实现
 */
export class WasmClusterServiceImpl implements WasmClusterService {
  private bridge: WasmBridge;
  private remotingService: WasmRemotingService;
  private rootContext: RootContext;
  private system: ActorSystem;
  private listeners: Map<number, ClusterEventListener> = new Map();
  private nextListenerId: number = 1;
  private initialized: boolean = false;

  /**
   * 构造函数
   * @param bridge WASM 桥接器
   * @param remotingService WASM 远程通信服务
   * @param system Actor 系统
   */
  constructor(bridge?: WasmBridge, remotingService?: WasmRemotingService, system?: ActorSystem) {
    this.bridge = bridge || WasmBridgeFactory.getInstance();
    this.system = system || new ActorSystem();
    this.rootContext = RootContexts.create(this.system);
    this.remotingService = remotingService || WasmRemotingFactory.getInstance(this.bridge, this.rootContext);
  }

  /**
   * 初始化集群
   * @param config 集群配置
   */
  async initialize(config: ClusterConfig): Promise<void> {
    if (this.initialized) {
      return;
    }

    // 确保 WASM 桥接和远程通信已初始化
    if (!this.bridge["initialized"]) {
      await this.bridge.initialize();
    }

    if (!this.remotingService["initialized"]) {
      await this.remotingService.initialize();
    }

    // 注册集群成员变化处理函数
    this.bridge.registerTSFunction('OnClusterMembershipEvent', this.handleMembershipEvent.bind(this));

    // 调用 Go 端初始化集群
    await this.bridge.invokeGoFunction('ClusterInitialize', config);
    
    this.initialized = true;
    console.log('WASM 集群服务初始化成功');
  }

  /**
   * 获取集群节点列表
   */
  async getNodes(): Promise<ClusterNode[]> {
    this.ensureInitialized();

    const nodesJson = await this.bridge.invokeGoFunction('ClusterGetNodes');
    return JSON.parse(nodesJson) as ClusterNode[];
  }

  /**
   * 查找集群中的 Actor
   */
  async getClusterActor(clusterKind: string, identity: string): Promise<PID> {
    this.ensureInitialized();

    const pidJson = await this.bridge.invokeGoFunction('ClusterGetActor', clusterKind, identity);
    if (!pidJson) {
      throw new Error(`找不到集群 Actor: ${clusterKind}/${identity}`);
    }

    const { address, id } = JSON.parse(pidJson);
    return new PID(address, id);
  }

  /**
   * 向集群 Actor 发送消息
   */
  async sendClusterMessage(clusterKind: string, identity: string, message: any, sender?: PID): Promise<void> {
    this.ensureInitialized();

    const pid = await this.getClusterActor(clusterKind, identity);
    await this.remotingService.sendMessage(pid, message, sender);
  }

  /**
   * 向集群 Actor 发送请求并等待响应
   */
  async requestClusterActor(clusterKind: string, identity: string, message: any, timeout: number = 5000): Promise<any> {
    this.ensureInitialized();

    return new Promise((resolve, reject) => {
      const timeoutId = setTimeout(() => {
        reject(new Error(`向集群 Actor 请求超时: ${clusterKind}/${identity}`));
      }, timeout);

      // 创建一个回调函数来处理响应
      const callbackId = this.bridge.createCallback((responseJson: string) => {
        clearTimeout(timeoutId);
        this.bridge.releaseCallback(callbackId);
        
        try {
          const response = JSON.parse(responseJson);
          resolve(response);
        } catch (error) {
          reject(error);
        }
      });

      // 调用 Go 端请求方法
      this.bridge.invokeGoFunction(
        'ClusterRequestActor',
        clusterKind,
        identity,
        JSON.stringify(message),
        callbackId,
        timeout
      ).catch(error => {
        clearTimeout(timeoutId);
        this.bridge.releaseCallback(callbackId);
        reject(error);
      });
    });
  }

  /**
   * 注册集群 Actor 类型
   */
  registerClusterKind(kind: string, props: Props): void {
    this.ensureInitialized();
    
    // 在本地注册 Actor
    this.system.registerClusterKind(kind, props);
    
    // 通知 Go 端注册 Actor 类型
    this.bridge.invokeGoFunction('ClusterRegisterKind', kind)
      .catch(error => console.error(`注册集群 Actor 类型失败: ${kind}`, error));
  }

  /**
   * 添加集群事件监听器
   */
  addMembershipListener(listener: ClusterEventListener): number {
    const id = this.nextListenerId++;
    this.listeners.set(id, listener);
    return id;
  }

  /**
   * 移除集群事件监听器
   */
  removeMembershipListener(listenerId: number): void {
    this.listeners.delete(listenerId);
  }

  /**
   * 优雅关闭集群
   */
  async shutdown(): Promise<void> {
    if (!this.initialized) {
      return;
    }

    await this.bridge.invokeGoFunction('ClusterShutdown');
    this.initialized = false;
    console.log('WASM 集群服务已关闭');
  }

  /**
   * 处理集群成员事件
   * @param eventJson 事件 JSON 字符串
   */
  private handleMembershipEvent(eventJson: string): void {
    try {
      const event = JSON.parse(eventJson) as MembershipEvent;
      
      // 通知所有监听器
      this.listeners.forEach(listener => {
        try {
          listener(event);
        } catch (error) {
          console.error('集群事件监听器处理失败:', error);
        }
      });
    } catch (error) {
      console.error('解析集群成员事件失败:', error);
    }
  }

  /**
   * 确保集群已初始化
   */
  private ensureInitialized(): void {
    if (!this.initialized) {
      throw new Error('WASM 集群服务尚未初始化');
    }
  }
}

/**
 * ActorSystem 扩展方法
 */
declare module '../actor/actorSystem' {
  interface ActorSystem {
    /**
     * 注册集群 Actor 类型
     * @param kind Actor 类型
     * @param props Actor 配置
     */
    registerClusterKind(kind: string, props: Props): void;
  }
}

// 扩展 ActorSystem
ActorSystem.prototype.registerClusterKind = function(kind: string, props: Props): void {
  // 在这里实现注册逻辑
  console.log(`注册集群 Actor 类型: ${kind}`);
  // 实际实现应该将 props 存储在某个地方以便后续查找
};

/**
 * WASM 集群服务工厂
 */
export class WasmClusterFactory {
  private static instance: WasmClusterServiceImpl;

  /**
   * 获取 WASM 集群服务实例
   * @param bridge 可选的 WASM 桥接器
   * @param remotingService 可选的远程通信服务
   * @param system 可选的 Actor 系统
   * @returns WASM 集群服务实例
   */
  static getInstance(bridge?: WasmBridge, remotingService?: WasmRemotingService, system?: ActorSystem): WasmClusterService {
    if (!WasmClusterFactory.instance) {
      WasmClusterFactory.instance = new WasmClusterServiceImpl(bridge, remotingService, system);
    }
    return WasmClusterFactory.instance;
  }
} 